﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

using Bricks.Component.Utils;


namespace Bricks.Component.Data
{
    /// <summary>
    ///     定义仓储模型中的数据标准操作
    /// </summary>
    /// <typeparam name="TEntity">动态实体类型</typeparam>
    /// <typeparam name="TKey">实体主键类型</typeparam>
    public interface IRepository<TEntity, in TKey> where TEntity : EntityBase<TKey>
    {
        #region 属性

        /// <summary>
        ///     获取 当前实体的查询数据集
        /// </summary>
        IQueryable<TEntity> Entities { get; }

        #endregion

        #region 公共方法

        /// <summary>
        ///     插入实体记录
        /// </summary>
        /// <param name="entity"> 实体对象 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        int Insert(TEntity entity, bool isSave = true);

        /// <summary>
        ///     批量插入实体记录集合
        /// </summary>
        /// <param name="entities"> 实体记录集合 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        int Insert(IEnumerable<TEntity> entities, bool isSave = true);

        /// <summary>
        ///     删除指定编号的记录
        /// </summary>
        /// <param name="id"> 实体记录编号 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        int Delete(TKey id, bool isSave = true);

        /// <summary>
        ///     删除实体记录
        /// </summary>
        /// <param name="entity"> 实体对象 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        int Delete(TEntity entity, bool isSave = true);

        /// <summary>
        ///     删除实体记录集合
        /// </summary>
        /// <param name="entities"> 实体记录集合 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        int Delete(IEnumerable<TEntity> entities, bool isSave = true);

        /// <summary>
        ///     删除所有符合特定表达式的数据
        /// </summary>
        /// <param name="predicate"> 查询条件谓语表达式 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        int Delete(Expression<Func<TEntity, bool>> predicate, bool isSave = true);

        /// <summary>
        ///     更新实体记录
        /// </summary>
        /// <param name="entity"> 实体对象 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        int Update(TEntity entity, bool isSave = true);

        /// <summary>
        /// 使用附带新值的实体信息更新指定实体属性的值
        /// </summary>
        /// <param name="propertyExpression">属性表达式</param>
        /// <param name="isSave">是否执行保存</param>
        /// <param name="entity">附带新值的实体信息，必须包含主键</param>
        /// <returns>操作影响的行数</returns>
        int Update(Expression<Func<TEntity, object>> propertyExpression, TEntity entity, bool isSave = true);

        /// <summary>
        /// 更新实体记录集合
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="isSave"></param>
        /// <returns></returns>
        int Update(IEnumerable<TEntity> entities, bool isSave = true);

        /// <summary>
        ///     查找指定主键的实体记录
        /// </summary>
        /// <param name="key"> 指定主键 </param>
        /// <returns> 符合编号的记录，不存在返回null </returns>
        TEntity GetByKey(TKey key);

        /// <summary>
        /// 获取下一个排序号
        /// </summary>
        /// <param name="sortname"></param>
        /// <returns></returns>
        int GetNextOrderNo(Expression<Func<TEntity, int?>> sortname);

        /// <summary>
        /// 获取指定集合的下一个排序号
        /// </summary>
        /// <param name="entities">指定集合</param>
        /// <param name="sortname">排序字段名称</param>
        /// <returns></returns>
        int GetNextOrderNo(IQueryable<TEntity> entities, Expression<Func<TEntity, int?>> sortname);
        
        /// <summary>
        /// 获取排序实体列表
        /// </summary>
        /// <param name="model"></param>
        /// <param name="entities"></param>
        /// <param name="sortname"></param>
        /// <param name="sortorder"></param>
        /// <returns></returns>
        IQueryable<TEntity> GetOrderEntities(TEntity model, IQueryable<TEntity> entities, string sortname, string sortorder);

        /// <summary>
        /// 执行SQL语句并返回受影响的行数
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        int ExeSqlCommon(string sql);

        /// <summary>
        /// 执行SQL语句并返回查询结果
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        IEnumerable<TEntity> SqlQueryCommon(string sql);

        /// <summary>
        /// 设置排序的统一方法（向上向下）
        /// </summary>
        /// <param name="entities">涉及的实体集合</param>
        /// <param name="id">选中的记录ID</param>
        /// <param name="orderColumn">排序列（注意此列需非空，否则可能异常）</param>
        /// <param name="upOrDown">向上或向下</param>
        /// <returns></returns>
        OperationResult SetOrder(IQueryable<TEntity> entities, TKey id, string orderColumn, string upOrDown);

        #endregion
    }
}